package com.s7.widget.recycler.helper;

import android.graphics.Color;

import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import com.s7.widget.recycler.adapter.BaseLoadMoreAdapter;
import com.s7.widget.recycler.listener.OnLoadDataListener;
import com.s7.widget.recycler.listener.Recycler;

import java.util.List;

public class LoadMoreHelper<T> implements SwipeRefreshLayout.OnRefreshListener, Recycler.OnLoadingListener {

    private boolean hasInitAdapter = false;

    private int page = 1;
    private int pageSize = 100;
    private boolean isAadditional = true;
    private BaseLoadMoreAdapter<T> mAdapter;
    private SwipeRefreshLayout mSwipeRefresh;
    private RecyclerView mRecycler;
    private RecyclerView.LayoutManager mManager;
    private RecyclerView.ItemDecoration mDecoration;
    private Recycler.OnCheckedChangeListener<T> mCheckedChange;
    private Recycler.OnClickListener<T> mClick;
    private Recycler.OnItemClickListener<T> mItemClick;
    private Recycler.OnItemLongClickListener<T> mItemLongClick;
    private OnLoadDataListener mLoadData;

    private boolean isLoad = false;

    protected LoadMoreHelper setPageSize(int pageSize) {
        this.pageSize = pageSize;
        return this;
    }

    public LoadMoreHelper setAadditional(boolean aadditional) {
        isAadditional = aadditional;
        return this;
    }

    protected LoadMoreHelper setSwipeRefresh(SwipeRefreshLayout mSwipeRefresh) {
        this.mSwipeRefresh = mSwipeRefresh;
        return this;
    }

    protected LoadMoreHelper setRecycler(RecyclerView mRecycler) {
        this.mRecycler = mRecycler;
        return this;
    }

    public LoadMoreHelper setManager(RecyclerView.LayoutManager mManager) {
        this.mManager = mManager;
        return this;
    }

    public LoadMoreHelper setDecoration(RecyclerView.ItemDecoration mDecoration) {
        this.mDecoration = mDecoration;
        return this;
    }

    protected LoadMoreHelper setAdapter(BaseLoadMoreAdapter<T> mAdapter) {
        this.mAdapter = mAdapter;
        return this;
    }

    protected LoadMoreHelper setLoadData(OnLoadDataListener mLoadData) {
        this.mLoadData = mLoadData;
        return this;
    }

    public LoadMoreHelper setCheckedChange(Recycler.OnCheckedChangeListener<T> mCheckedChange) {
        this.mCheckedChange = mCheckedChange;
        return this;
    }

    protected LoadMoreHelper setClick(Recycler.OnClickListener<T> mClick) {
        this.mClick = mClick;
        return this;
    }

    protected LoadMoreHelper setItemClick(Recycler.OnItemClickListener<T> mItemClick) {
        this.mItemClick = mItemClick;
        return this;
    }

    protected LoadMoreHelper setItemLongClick(Recycler.OnItemLongClickListener<T> mItemLongClick) {
        this.mItemLongClick = mItemLongClick;
        return this;
    }

    public void initAdapter(){

        if (mAdapter == null || mRecycler == null || mManager == null) {
            return;
        }

        if(mSwipeRefresh != null && mLoadData != null) {
            mSwipeRefresh.setOnRefreshListener(this);
        }

        onManager();

        if (mDecoration != null) {
            mRecycler.addItemDecoration(mDecoration);
        }

        mAdapter.setAadditional(isAadditional)
                .setPageSize(pageSize)
                .setCheckedChange(mCheckedChange)
                .setClick(mClick)
                .setItemClick(mItemClick)
                .setItemLongClick(mItemLongClick);
        if (mLoadData != null) {
            mAdapter.setLoadingListener(this);
        }
        mRecycler.setAdapter(mAdapter);
        hasInitAdapter = true;
    }

    private void onManager() {
        if (mManager instanceof StaggeredGridLayoutManager) {
            ((StaggeredGridLayoutManager) mManager).setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
        }
        mRecycler.setLayoutManager(mManager);
        mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (mManager instanceof StaggeredGridLayoutManager) {
                    ((StaggeredGridLayoutManager) mManager).invalidateSpanAssignments();
                }
            }
        });
    }

    @Override
    public void onRefresh() {
        if (isLoad()) {
            return;
        }
        page = 1;
        isLoad = true;
        mLoadData.onLoadData(page);
    }

    @Override
    public void onReload() {
        if (isLoad()) {
            return;
        }
        page = 1;
        isLoad = true;
        setSwipeRefresh(true);
        mLoadData.onLoadData(page);
    }

    @Override
    public void onLoading() {
        if (isLoad()) {
            return;
        }
        isLoad = true;
        mLoadData.onLoadData(page);
    }

    private void setSwipeRefresh(boolean flag) {
        if (mSwipeRefresh != null) {
            if (flag) {
                if (!mSwipeRefresh.isRefreshing()) {
                    mSwipeRefresh.setRefreshing(true);
                }
            } else {
                if (mSwipeRefresh.isRefreshing()) {
                    mSwipeRefresh.setRefreshing(false);
                }
            }
        }
    }

    private boolean isLoad() {
        if (isLoad) {
            setSwipeRefresh(false);
        }
        return isLoad;
    }

    public void setLayoutManager(RecyclerView.LayoutManager layoutManager) {
        if (mRecycler != null && mAdapter != null && layoutManager != null) {
            mManager = layoutManager;
            onManager();
            mAdapter.onAttachedToRecyclerView(mRecycler);
            notifyAdapter();
        }
    }

    public void loadFirstPage() {
        page = 1;
        if(!hasInitAdapter){
            initAdapter();
        }

        if (mLoadData != null) {
            setSwipeRefresh(true);
            mLoadData.onLoadData(page);
            isLoad = true;
        }
    }

    public void notifyAdapter(List<T> datas) {
        if (page == 1) {
            setSwipeRefresh(false);
            mAdapter.onRefresh(datas);
        } else {
            mAdapter.addDatas(datas);
        }
        isLoad = false;
        page++;
    }

    public void notifyAdapter(T data) {
        mAdapter.addData(data);
    }

    public void notifyAdapter() {
        mAdapter.notifyDataSetChanged();
    }

    public void notifyNull() {
        if (page == 1) {
            setSwipeRefresh(false);
            mAdapter.setNull(true);
        } else {
            page = 1;
            mAdapter.getDatas().clear();
            mAdapter.setNull(true);
        }
        isLoad = false;
    }

    public void notifyError() {
        if (page == 1) {
            setSwipeRefresh(false);
            mAdapter.setError(true);
        } else {
            mAdapter.setLoadError(true);
        }
        isLoad = false;
    }

    public void notifyRefresh(List<T> datas) {
        mAdapter.onRefresh(datas);
    }

    public void notifyReplace(int position, T data) {
        mAdapter.onReplace(position, data);
    }

    public void notifyRemove(int position) {
        mAdapter.onRemove(position);
    }

    public List<T> getData() {
        return mAdapter.getDatas();
    }

    public static class Builder<T> {
        private int pageSize = 100;
        private BaseLoadMoreAdapter<T> mAdapter;
        private SwipeRefreshLayout mSwipeRefresh;
        private RecyclerView mRecycler;
        private RecyclerView.LayoutManager mManager;
        private RecyclerView.ItemDecoration mDecoration;
        private Recycler.OnCheckedChangeListener<T> mCheckedChange;
        private Recycler.OnClickListener<T> mClick;
        private Recycler.OnItemClickListener<T> mItemClick;
        private Recycler.OnItemLongClickListener<T> mItemLongClick;
        private OnLoadDataListener mLoadData;
        private boolean isAadditional = true;

        public Builder setPageSize(int pageSize) {
            this.pageSize = pageSize;
            return this;
        }

        public Builder setAadditional(boolean isAadditional) {
            this.isAadditional = isAadditional;
            return this;
        }

        public Builder setSwipeRefresh(SwipeRefreshLayout mSwipeRefresh) {
            return setSwipeRefresh(mSwipeRefresh, Color.RED, Color.YELLOW, Color.BLUE, Color.GREEN);
        }

        public Builder setSwipeRefresh(SwipeRefreshLayout mSwipeRefresh, int... colors) {
            this.mSwipeRefresh = mSwipeRefresh;
            this.mSwipeRefresh.setColorSchemeColors(colors);
            return this;
        }

        public Builder setRecycler(RecyclerView mRecycler, final RecyclerView.LayoutManager mManager) {
            return setRecycler(mRecycler, mManager, null);
        }

        public Builder setRecycler(RecyclerView mRecycler, final RecyclerView.LayoutManager mManager,
                                   RecyclerView.ItemDecoration mDecoration) {
            this.mRecycler = mRecycler;
            this.mManager = mManager;
            this.mDecoration = mDecoration;
            return this;
        }

        public Builder setAdapter(BaseLoadMoreAdapter<T> mAdapter) {
            return setAdapter(mAdapter, true);
        }

        public Builder setAdapter(BaseLoadMoreAdapter<T> mAdapter, boolean isFooter) {
            return setAdapter(mAdapter, true, isFooter);
        }

        public Builder setAdapter(BaseLoadMoreAdapter<T> mAdapter, boolean isLoad, boolean isFooter) {
            this.mAdapter = mAdapter;
            this.mAdapter.setLoad(isLoad).setFooter(isFooter);
            return this;
        }

        public Builder setCheckedChange(Recycler.OnCheckedChangeListener<T> mCheckedChange) {
            this.mCheckedChange = mCheckedChange;
            return this;
        }

        public Builder setClick(Recycler.OnClickListener<T> mClick) {
            this.mClick = mClick;
            return this;
        }

        public Builder setItemClick(Recycler.OnItemClickListener<T> mItemClick) {
            this.mItemClick = mItemClick;
            return this;
        }

        public Builder setItemLongClick(Recycler.OnItemLongClickListener<T> mItemLongClick) {
            this.mItemLongClick = mItemLongClick;
            return this;
        }

        public Builder setLoadData(OnLoadDataListener mLoadData) {
            this.mLoadData = mLoadData;
            return this;
        }

        public <T> LoadMoreHelper<T> build() {
            LoadMoreHelper mHelper = new LoadMoreHelper<T>()
                    .setPageSize(pageSize)
                    .setAadditional(isAadditional)
                    .setSwipeRefresh(mSwipeRefresh)
                    .setRecycler(mRecycler)
                    .setManager(mManager)
                    .setDecoration(mDecoration)
                    .setAdapter(mAdapter)
                    .setLoadData(mLoadData)
                    .setCheckedChange(mCheckedChange)
                    .setClick(mClick)
                    .setItemClick(mItemClick)
                    .setItemLongClick(mItemLongClick);
            mHelper.initAdapter();
            return mHelper;
        }
    }
}
